#!/usr/bin/env python

# -*- coding: utf-8 -*-

"""
	Copyright (C) 2008  Michael Ughetto <telimektar1er@gmail.com>

	This file is part of Danuve.
	Danuve is a easy to use numerical tool meant to solve chain of oscillators

	Danuve is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	Danuve is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Danuve.  If not, see <http://www.gnu.org/licenses/>.
""" 

import sys, os
import ConfigParser
import tempfile

from optparse import OptionParser

from danuve import danuve_readconf
from danuve.danuve_physics import chaine_oscillateurs

try :
	import psyco
	psyco.full()
except ImportError:
	print "by installing Psyco you can impressively improve the speed of Danuve"
	print "Psyco is freely available at http://psyco.sourceforge.net/"

# Definition of global vars

CONF_URI = "oscillator.ini"
OUTPUT_URI = tempfile.gettempdir() + "/solved.gpt"

required_sections = ['Look','Init','Carac','Other']
required_look = ['Name','Structure']
required_init = ['init_speeds','init_positions']
required_carac = ['duration','timestep','carac_springs','carac_masses']
required_other = ['author','date']

# Getting other vars from option, in case there are option ;)

usage = """%prog [-a|--algo] <str> [-c|--conf] <str> [-o|--output] <str> \
[-s|--session] <str> [-t|--timer] <float>"""

option_parser = OptionParser(usage=usage, version="%prog 0.1a")

option_parser.set_defaults(conf_uri=CONF_URI, output_uri=OUTPUT_URI, \
	algo="euler")

option_parser.add_option("-a", "--algo", action="store", dest="algo", \
	type="choice", choices=['euler', 'rk4'], \
	help="Choose the algorithm used for the simulation within this list :\
	 euler, rk4 or heun")
option_parser.add_option("-c", "--conf", action="store", dest="conf_uri",\
	help="Tell the script where to find the system to solve")
option_parser.add_option("-o", "--output", action="store", \
	dest="output_uri", help="Tell the script where to write the results")
option_parser.add_option("-s", "--session", action="store", \
	dest="session_name", help="Allow you to interrupt and resume work, "
		"not implemented yet")
option_parser.add_option("-t", "--timer", action="store", type="float", \
	dest="work_time", help="Set the maximum time that your computer will work "
		"on the simulation (in seconds)")

(options, args) = option_parser.parse_args()

# Build the path to session save file (if available)

if options.session_name:
	sess_path = os.path.expanduser('~/.danuve/' + \
		options.session_name + '.sess')
	try:
		session_file = open(sess_path,'r')
		sess_file_exists = True
	except IOError:
		sess_file_exists = False
else:
	sess_file_exists = False

# Verify the content of the configuration file

if not options.session_name or not sess_file_exists:
	conf_file = ConfigParser.RawConfigParser()

	try:
		conf_file.read(options.conf_uri)
	except ConfigParser.MissingSectionHeaderError:
		print "It seems that you're missing a section header"
		sys.exit(1)
	print "Opening", options.conf_uri, "..."

	danuve_readconf.section_check(conf_file, required_sections)
	danuve_readconf.option_check(conf_file, 'Look', required_look)
	danuve_readconf.option_check(conf_file, 'Init', required_init)
	danuve_readconf.option_check(conf_file, 'Carac', required_carac)
	danuve_readconf.option_check(conf_file, 'Other', required_other)

	# Extraction of the systeme Init data

	structure = conf_file.get('Look', 'Structure')
	danuve_readconf.check_struct(structure)

	print "\nThe configuration file is correct"
	print "We are gathering its informations\n"

	speeds = danuve_readconf.get_list(conf_file, 'Init', 'init_speeds')
	positions = danuve_readconf.get_list(conf_file, 'Init', 'init_positions')

	carac_masses = danuve_readconf.get_list(conf_file, 'Carac', 'carac_masses')
	for masse in carac_masses:
		if masse == 0:
			print "Masses MUST be different from 0\n"
			sys.exit(1)
	duration = danuve_readconf.get_data(conf_file, 'Carac', 'duration')
	timestep = danuve_readconf.get_data(conf_file, 'Carac', 'timestep')

	left_spring, right_spring = danuve_readconf.get_spring(conf_file,structure)

	#Initialisation of the physic system object

	chain = oscillators_chain(carac_masses, positions, speeds, \
		left_spring, right_spring, timestep, duration)

	#Solving the initialized object, Notice : Threads rox

	output_file = open(options.output_uri, 'w')
	chain.set_solve_info(output_file, options.algo)
	if options.work_time:
		chain.work_time = options.work_time
	chain.start()

else:
	print "Session are not implemented yet (contributions are welcomed)"
